package com.bruce.utils.json;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONPath;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.github.fge.jsonpatch.JsonPatch;
import com.github.fge.jsonpatch.diff.JsonDiff;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.jayway.jsonpath.JsonPath;
import foodev.jsondiff.GsonDiff;
import foodev.jsondiff.jsonwrap.jackson.JacksonJsonObject;
import org.apache.commons.lang3.StringUtils;
import org.skyscreamer.jsonassert.JSONCompare;
import org.skyscreamer.jsonassert.JSONCompareMode;
import org.skyscreamer.jsonassert.JSONCompareResult;

import java.io.IOException;
import java.io.Reader;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author luotuan
 * @Description
 * @create 2020-06-23 13:34
 **/
public class GsonUtils {
    private static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
    private static Gson gson = new GsonBuilder().registerTypeAdapter(Double.class, new JsonSerializer<Double>() {
        @Override
        public JsonElement serialize(Double src, Type typeOfSrc, JsonSerializationContext context) {
            if (src == src.longValue())
                return new JsonPrimitive(src.longValue());
            return new JsonPrimitive(src);
        }
    }).setDateFormat(DEFAULT_DATE_FORMAT).create();


    public static String toJson(Object object) {
        return gson.toJson(object);
    }

    public static <T> T toObject(String paramJson, Class<T> clazz) {
        return gson.fromJson(paramJson, clazz);
    }

    public static <T> T toObject(Reader reader, Class<T> clazz) {
        return gson.fromJson(reader, clazz);
    }

    @SuppressWarnings("unchecked")
    public static <T> List<T> toObjects(String paramJson, Class<T> clazz) {
        return (List<T>) gson.fromJson(paramJson, clazz);
    }

    public static Map<String, Object> toMap(String paramJson) {
        return gson.fromJson(paramJson, new TypeToken<Map<String, Object>>() {
        }.getType());
    }

    public static LinkedHashMap<String, Object> toLinkedHashMap(String paramJson) {
        return gson.fromJson(paramJson, new TypeToken<LinkedHashMap<String, Object>>() {
        }.getType());
    }

    public static JsonObject compareJson(JsonElement object1, JsonElement object2) {
        GsonDiff gsonDiff = new GsonDiff();
        JsonObject result = null;
        boolean isNull = object1 == null || object2 == null || object1.isJsonNull() || object2.isJsonNull();
        if (!isNull) {
            if (object1.isJsonArray()) {
                // 如果是数组，则转换成JsonObject
                JsonObject jsonObject1 = new JsonObject();
                jsonObject1.add("root", object1);
                JsonObject jsonObject2 = new JsonObject();
                jsonObject2.add("root", object2);
                result = gsonDiff.diff(jsonObject1, jsonObject2);
            } else {
                result = gsonDiff.diff(object1, object2);
            }
        } else {
            result = new JsonObject();
        }
        return result;
    }

    public static void main(String[] args) throws Exception {
        String filePath = "F:\\浩鲸云科技\\开发\\设计中心\\bo融合\\";
        String str1 = new String(Files.readAllBytes(Paths.get(filePath+"json1.txt")), StandardCharsets.UTF_8);
        String str2 = new String(Files.readAllBytes(Paths.get(filePath+"json2.txt")), StandardCharsets.UTF_8);
        //去除DEL节点
        JSONObject jsonObject = JSON.parseObject(str2);
        Map<String,Object> mapResult = JSONPath.paths(jsonObject);
        mapResult = mapResult.entrySet().stream().filter(entry->{
            if(entry.getKey().contains("actType")){
                String value = (String) entry.getValue();
                return StringUtils.equals(value, "DEL");
            }
            return false;
        }).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
        List<String> jsonPathsList = new ArrayList<>(mapResult.keySet());
        jsonPathsList.replaceAll(k->k.replace("/actType",""));
        jsonPathsList.forEach(jsonPath->JSONPath.remove(jsonObject,jsonPath));
        str2 = jsonObject.toJSONString();
        //比较
        ObjectMapper mapper = new ObjectMapper();
        JsonNode beforeNode = mapper.readTree(str1);
        JsonNode afterNode = mapper.readTree(str2);
        JsonNode jsonNodeResult = JsonDiff.asJson(beforeNode,afterNode);
        System.out.println(jsonNodeResult.toString());
        List<JsonDiffDto> diffDtos = GsonUtils.gson.fromJson(jsonNodeResult.toString(), new TypeToken<List<JsonDiffDto>>(){}.getType());
        //填充
        diffDtos.forEach(diff->{
            System.out.println(diff.getOp()+"****"+diff.getPath());
        });
        System.out.println("********************");
    }
}
